package com.ecp.commons.db;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Repository;

import com.ecp.commons.bean.Page;
import com.ecp.commons.serialization.SerializableObject;

@Repository
public abstract class GenericServiceImpl<T> implements GenericService<T> {
	protected static final Logger LOGGER = Logger.getLogger("updateUser");

	@Resource(name = "genericDAO")
	private GenericDAO<T>	genericDAO;

	protected T				t	= null;

	@SuppressWarnings("unchecked")
	public GenericServiceImpl() {
		Type genType = this.getClass().getGenericSuperclass();
		if (genType instanceof ParameterizedType) {
			Class<?> cls = (Class<?>) ((ParameterizedType) genType).getActualTypeArguments()[0];
			try {
				t = (T) cls.newInstance();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public int generateId(T t) throws Exception {
		return genericDAO.generateId(t);
	}

	@Override
	public int generateId() throws Exception {
		return genericDAO.generateId(t);
	}

	@Override
	public void add(T t) throws Exception {
		genericDAO.add(t);
	}

	@Override
	public void addBatch(List<T> list, boolean inTrans) throws Exception {
		genericDAO.addBatch(list, inTrans);
	}

	@Override
	public void update(T t) throws Exception {
		Exception e = new Exception();
		StackTraceElement[] trace = e.getStackTrace();
		StringBuilder sb=new StringBuilder("");
		for (int i=0; i < trace.length; i++){
	        sb.append("\t" + trace[i]+"\r\n");
		}
		genericDAO.update(t);
	}

	@Override
	public void delete(Serializable pk) throws Exception {
		genericDAO.delete(pk, t);
	}

	@Override
	public void delete(Serializable pk, T t) throws Exception {
		genericDAO.delete(pk, t);
	}

	@Override
	public void deleteBatch(List<?> pks, boolean inTrans) throws Exception {
		genericDAO.deleteBatch(pks, t, inTrans);
	}

	@Override
	public void deleteBatch(List<?> pks, T t, boolean inTrans) throws Exception {
		genericDAO.deleteBatch(pks, t, inTrans);
	}

	@Override
	public T load(Serializable pk) throws Exception {
		return genericDAO.load(pk, t);
	}

	@Override
	public T load(Serializable pk, T t) throws Exception {
		return genericDAO.load(pk, t);
	}

	@Override
	public T getEntity(String sql, Object[] args) throws Exception {
		return (T) genericDAO.getEntity(sql, args, t);
	}

	@Override
	public T getEntity(String sql, Object[] args, T t) throws Exception {
		return (T) genericDAO.getEntity(sql, args, t);
	}

	@Override
	public T getEntity(String[] keys, Object[] args) throws Exception {
		return (T) genericDAO.getEntity(keys, args, t);
	}

	@Override
	public T getEntity(String[] keys, Object[] args, T t) throws Exception {
		return (T) genericDAO.getEntity(keys, args, t);
	}

	@Override
	public List<T> getAll() throws Exception {
		return genericDAO.getAll(t);
	}

	@Override
	public List<T> getAll(T t) throws Exception {
		return genericDAO.getAll(t);
	}

	@Override
	public List<T> getEntityList(String sql, Object[] args) throws Exception {
		return genericDAO.getEntityList(sql, args, t);
	}

	@Override
	public List<T> getEntityList(String sql, Object[] args, T t) throws Exception {
		return genericDAO.getEntityList(sql, args, t);
	}

	@Override
	public List<T> getEntityList(String sql, Object[] args, T t, Page page) throws Exception {
		return genericDAO.getEntityList(sql, args, t, page);
	}

	@Override
	public List<T> getEntityList(String[] keys, Object[] args, Page page) throws Exception {
		return genericDAO.getEntityList(keys, args, page, t);
	}

	@Override
	public List<T> getEntityList(String[] keys, Object[] args, Page page, T t) throws Exception {
		return genericDAO.getEntityList(keys, args, page, t);
	}

	@Override
	public List<Integer> getEntityIdList(String sql, Object[] args) throws Exception {
		return genericDAO.getEntityIdList(sql, args);
	}

	@Override
	public List<Integer> getEntityIdList(String sql, Object[] args, Page page) throws Exception {
		return genericDAO.getEntityIdList(sql, args, page);
	}

	@Override
	public int execute(String sql, Object[] args) {
		return genericDAO.execute(sql, args, t);
	}

	@Override
	public int execute(String sql, Object[] args, T t) {
		return genericDAO.execute(sql, args, t);
	}

	@Override
	public List<T> getEntityList(Map<String, JSONObject> map, T t, Page page, String orderBy) throws Exception {
		return genericDAO.getEntityList(map, t, page, orderBy);
	}

	@Override
	public List<JSONObject> search(String sql, Object[] args, Page page) throws Exception {
		return genericDAO.search(sql, args, page);
	}

	@Override
	public JSONObject toJSON(T t, String[] keys) {
		return this.toJSON(t, keys, "");
	}

	@Override
	public JSONObject toJSON(T t, String[] keys, String prefix) {
		if (prefix == null) {
			prefix = "";
		}
		JSONObject jobj = new JSONObject();
		SerializableObject obj = (SerializableObject) t;
		try {
			if (keys == null) {
				for (String key : obj.keySet()) {
					jobj.put(prefix + key, obj.getString(key));
				}
			} else {
				for (String key : keys) {
					if (obj.keySet().contains(key)) {
						jobj.put(prefix + key, obj.getString(key));
					}
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return jobj;
	}

	@Override
	public JSONArray toJSONArray(List<T> list, String keys[]) {
		JSONArray jarr = new JSONArray();
		for (T t : list) {
			jarr.put(this.toJSON(t, keys, ""));
		}
		return jarr;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T fromJSON(JSONObject jobj) {
		SerializableObject bean = null;
		try {
			bean = (SerializableObject) ((SerializableObject) t).getClass().newInstance();
			for (String key : bean.keySet()) {
				String value = jobj.getString(key);
				if (value != null) {
					bean.set(key, value);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return (T) bean;
	}

	@Override
	public List<T> fromJSONArray(JSONArray jarr) {
		List<T> list = new LinkedList<T>();
		try {
			for (int i = 0; i < jarr.length(); i++) {
				list.add(this.fromJSON(jarr.getJSONObject(i)));
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T copy(T t) {	
		if (t == null) {
			return null;
		}
		SerializableObject old = (SerializableObject) t;
		SerializableObject bean = null;
		try {
			bean = (SerializableObject) old.getClass().newInstance();
			for (String key : old.keySet()) {
				bean.set(key, old.getString(key));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return (T) bean;
	}
}
